package org.lanyu.springainovel.common.util;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.json.JsonMapper;
import lombok.extern.slf4j.Slf4j;
import org.lanyu.springainovel.common.entity.ServerConfig;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
public class ConversionUtil {
    public ConversionUtil() { super(); }

    /**
     * 解析单个 mcpServers �?jsonNode �?ServerConfig
     * @param serverName 服务器名
     * @param serverNode 该服务器�?jsonNode
     * @param type 类型（sse/stdio/npx�?     * @return ServerConfig �?null
     */
    public static ServerConfig parseServerConfigFromJson(String serverName, JsonNode serverNode, String type) {
        try {
            if ("sse".equalsIgnoreCase(type)) {
                String url = serverNode.path("url").asText("");
                if (url.isEmpty()) return null;
                ServerConfig config = new ServerConfig();
                config.setName(serverName);
                config.setUrl(url);
                config.setEnabled(true);
                // headers
                if (serverNode.has("headers")) {
                    Map<String, String> headers = JsonMapper.builder().build().convertValue(serverNode.get("headers"), Map.class);
                    config.setHeaders(headers);
                }
                // sseEndpoint
                if (serverNode.has("sseEndpoint")) {
                    config.setSseEndpoint(serverNode.get("sseEndpoint").asText("/sse"));
                }
                // timeout
                if (serverNode.has("timeout")) {
                    try {
                        config.setTimeout(Duration.ofMillis(serverNode.get("timeout").asLong()));
                    } catch (Exception ignored) {}
                }
                return config;
            } else if ("stdio".equalsIgnoreCase(type)) {
                // 兼容 command 直接定义或通过 args 传递的两种方式
                List<String> commandList = new ArrayList<>();

                // 解析主命�?
                String command = serverNode.path("command").asText("");
                if (!command.isEmpty()) {
                    commandList.add(command);
                }

                // 解析参数列表
                JsonNode argsNode = serverNode.path("args");
                if (argsNode.isArray() && !argsNode.isEmpty()) {
                    for (JsonNode argNode : argsNode) {
                        commandList.add(argNode.asText());
                    }
                }

                // 命令为空时返回null
                if (commandList.isEmpty()) return null;

                ServerConfig config = new ServerConfig();
                config.setName(serverName);
                config.setUrl("stdio://" + serverName);
                config.setEnabled(true);

                // 解析环境变量和工作目�?
                Map<String, String> stdioConfig = new ConcurrentHashMap<>();
                if (serverNode.has("workingDirectory")) {
                    stdioConfig.put("workingDirectory", serverNode.get("workingDirectory").asText(""));
                }
                if (serverNode.has("env")) {
                    Map<String, String> env = JsonMapper.builder().build()
                            .convertValue(serverNode.get("env"), new TypeReference<Map<String, String>>() {});
                    stdioConfig.putAll(env);
                }

                // 存储命令和参�?
                stdioConfig.put("command", String.join(" ", commandList));
                stdioConfig.put("args", JsonMapper.builder().build().writeValueAsString(commandList));

                // 解析超时时间(�?
                if (serverNode.has("timeout")) {
                    stdioConfig.put("timeout", serverNode.get("timeout").asText());
                    config.setTimeout(Duration.ofSeconds(serverNode.get("timeout").asLong()));
                }

                config.setHeaders(stdioConfig);
                return config;
            } else if ("npx".equalsIgnoreCase(type)) {
                // 解析NPX类型的配�?
                return parseNpxConfig(serverName, serverNode);
            }
        } catch (Exception e) {
            log.error("mcp配置json格式错误：{}，错误json报文:{}",e.getMessage(), serverNode);
        }
        return null;
    }

    /**
     * 解析NPX类型的配�?     */
    private static ServerConfig parseNpxConfig(String serverName, JsonNode serverNode) {
        // 解析主命令，默认为npx
        String command = serverNode.path("command").asText("npx");
        
        // 解析参数列表
        List<String> args = new ArrayList<>();
        JsonNode argsNode = serverNode.path("args");
        if (argsNode.isArray() && !argsNode.isEmpty()) {
            for (JsonNode argNode : argsNode) {
                args.add(argNode.asText());
            }
        }
        
        // 参数为空时返回null
        if (args.isEmpty()) {
            log.warn("NPX配置[{}]缺少args参数", serverName);
            return null;
        }

        ServerConfig config = new ServerConfig();
        config.setName(serverName);
        config.setCommand(command);
        config.setArgs(args);
        config.setUrl("npx://" + serverName);
        config.setEnabled(true);

        // 解析环境变量
        Map<String, String> env = new ConcurrentHashMap<>();
        if (serverNode.has("env")) {
            Map<String, String> envMap = JsonMapper.builder().build()
                    .convertValue(serverNode.get("env"), new TypeReference<Map<String, String>>() {});
            env.putAll(envMap);
        }
        config.setEnv(env);

        // 解析工作目录
        if (serverNode.has("workingDirectory")) {
            config.setWorkingDirectory(serverNode.get("workingDirectory").asText(""));
        }

        // 解析超时时间
        if (serverNode.has("timeout")) {
            try {
                config.setTimeout(Duration.ofSeconds(serverNode.get("timeout").asLong()));
            } catch (Exception e) {
                config.setTimeout(Duration.ofSeconds(600)); // 默认10分钟
            }
        } else {
            config.setTimeout(Duration.ofSeconds(600)); // 默认10分钟
        }

        return config;
    }
}
